package com.hsmpay.tencent;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.digest.DigestUtils;

import com.hsmpay.tencent.common.RandomStringGenerator;
import com.hsmpay.tencent.protocol.pay_protocol.PublicScanPayReqData;
import com.hsmpay.tencent.service.ScanPayService;


public class Main {

    public static void main(String[] args) {

        try {

            //--------------------------------------------------------------------
            //温馨提示，第一次使用该SDK时请到com.hsmpay.tencent.common.Configure类里面进行配置
            //--------------------------------------------------------------------



            //--------------------------------------------------------------------
            //PART One:基础组件测试
            //--------------------------------------------------------------------

            //1）https请求可用性测试
            //HTTPSPostRquestWithCert.test();

            //2）测试项目用到的XStream组件，本项目利用这个组件将Java对象转换成XML数据Post给API
            //XStreamTest.test();


            //--------------------------------------------------------------------
            //PART Two:基础服务测试
            //--------------------------------------------------------------------

            //1）测试被扫支付API
            //PayServiceTest.test();

            //2）测试被扫订单查询API
            //PayQueryServiceTest.test();

            //3）测试撤销API
            //温馨提示，测试支付API成功扣到钱之后，可以通过调用PayQueryServiceTest.test()，将支付成功返回的transaction_id和out_trade_no数据贴进去，完成撤销工作，把钱退回来 ^_^v
            //ReverseServiceTest.test();

            //4）测试退款申请API
            //RefundServiceTest.test();

            //5）测试退款查询API
            //RefundQueryServiceTest.test();

            //6）测试对账单API
            //DownloadBillServiceTest.test();


            //本地通过xml进行API数据模拟的时候，先按需手动修改xml各个节点的值，然后通过以下方法对这个新的xml数据进行签名得到一串合法的签名，最后把这串签名放到这个xml里面的sign字段里，这样进行模拟的时候就可以通过签名验证了
           // Util.log(Signature.getSignFromResponseString(Util.getLocalXMLString("/test/com/tencent/business/refundqueryserviceresponsedata/refundquerysuccess2.xml")));

            //Util.log(new Date().getTime());
            //Util.log(System.currentTimeMillis());

            /**
             * @param authCode 这个是扫码终端设备从用户手机上扫取到的支付授权号，这个号是跟用户用来支付的银行卡绑定的，有效期是1分钟
             * @param body 要支付的商品的描述信息，用户会在支付成功页面里看到这个信息
             * @param attach 支付订单里面可以填的附加数据，API会将提交的这个附加数据原样返回
             * @param outTradeNo 商户系统内部的订单号,32个字符内可包含字母, 确保在商户系统唯一
             * @param totalFee 订单总金额，单位为“分”，只能整数
             * @param deviceInfo 商户自己定义的扫码支付终端设备号，方便追溯这笔交易发生在哪台终端设备上
             * @param spBillCreateIP 订单生成的机器IP
             * @param timeStart 订单生成时间， 格式为yyyyMMddHHmmss，如2009年12 月25 日9 点10 分10 秒表示为20091225091010。时区为GMT+8 beijing。该时间取自商户服务器
             * @param timeExpire 订单失效时间，格式同上
             * @param goodsTag 商品标记，微信平台配置的商品标记，用于优惠券或者满减使用
             */
        	System.out.println("111111");
        	//ScanPayReqData scanPayReqData = new ScanPayReqData("130401726222916624", "测试", "5566", String.valueOf(System.currentTimeMillis()), 1, "WEB", "36.110.47.23", "20160913204710", "20160913205510", "1111");
        	//ScanPayService scanPayService = new ScanPayService();
        	//String request = scanPayService.request(scanPayReqData);
        	PublicScanPayReqData scanPayReqData = new PublicScanPayReqData("o8j3awFhMRtks46CSr-zLhrrHDYs","","http://weixin.zhijianzhuan.com.cn/proOneMobile/scanPay/scanPayNL_JQNotify.action","JSAPI", "测试", "5566", String.valueOf(System.currentTimeMillis()), 1, "WEB", "36.110.47.23", "20160915201010", "20160915250510", "");
        	ScanPayService scanPayService = new ScanPayService();
        	String request = scanPayService.request(scanPayReqData);
        	System.out.println(request);
        	
        	
        	

        } catch (Exception e){
        	e.printStackTrace();
            //Util.log(e.getMessage());
        }
      
    }
    
    //@Test
    public void test() throws Exception{
    	PublicScanPayReqData scanPayReqData = new PublicScanPayReqData("o8j3awFhMRtks46CSr-zLhrrHDYs","","http://weixin.zhijianzhuan.com.cn/proOneMobile/scanPay/scanPayNL_JQNotify.action","JSAPI", "测试", "5566", String.valueOf(System.currentTimeMillis()), 1, "WEB", "36.110.47.23", "20160914133910", "20160914134910", "");
    	String info= WXPay.requestScanPayService(scanPayReqData);
    	System.out.println(info);
    }
    //@Test
    public void md5(){
    	String time =String.valueOf(System.currentTimeMillis());
    	String nonceStr=RandomStringGenerator.getRandomStringByLength(32);
    	System.out.println("timeStamp: "+time);
    	System.out.println("nonceStr: "+nonceStr);
    	String MD5Key = "cHvacUCpCC4lSmFkaLm0PhpBz2cdDVuh";
    	 Map<String, String> map = new HashMap<>();
    	 map.put("appId", "wx681256660695b62f");
    	 map.put("timeStamp", time);
    	 map.put("nonceStr", nonceStr);
    	 map.put("package", "prepay_id=wx2016091415211846011031b40154853067");
    	 map.put("signType", "MD5");
    	 
    	 Map<String,String> params = SignUtils.paraFilter(map);
         StringBuilder buf = new StringBuilder((params.size() +1) * 10);
         SignUtils.buildPayParams(buf,params,false);
         String preStr = buf.toString();
         String sign = MD5.sign(preStr, "&key=" + MD5Key, "utf-8");
         System.out.println("sign:"+sign);
         map.put("sign", sign);
    }
    
  

}
class SignUtils{
	  public static Map<String, String> paraFilter(Map<String, String> sArray) {
	        Map<String, String> result = new HashMap<String, String>(sArray.size());
	        if (sArray == null || sArray.size() <= 0) {
	            return result;
	        }
	        for (String key : sArray.keySet()) {
	            String value = sArray.get(key);
	            if (value == null || value.equals("") || key.equalsIgnoreCase("sign")) {
	                continue;
	            }
	            result.put(key, value);
	        }
	        return result;
	    }
	  
	  public static void buildPayParams(StringBuilder sb,Map<String, String> payParams,boolean encoding){
	        List<String> keys = new ArrayList<String>(payParams.keySet());
	        Collections.sort(keys);
	        for(String key : keys){
	            sb.append(key).append("=");
	            if(encoding){
	                sb.append(urlEncode(payParams.get(key)));
	            }else{
	                sb.append(payParams.get(key));
	            }
	            sb.append("&");
	        }
	        sb.setLength(sb.length() - 1);
	    }
	  public static String urlEncode(String str){
	        try {
	            return URLEncoder.encode(str, "UTF-8");
	        } catch (Throwable e) {
	            return str;
	        } 
	    }
} 
class MD5 {
	 public static String sign(String text, String key, String input_charset) {
	    	text = text + key;
	        return DigestUtils.md5Hex(getContentBytes(text, input_charset)).toUpperCase();
	    }
	 private static byte[] getContentBytes(String content, String charset) {
	        if (charset == null || "".equals(charset)) {
	            return content.getBytes();
	        }
	        try {
	            return content.getBytes(charset);
	        } catch (UnsupportedEncodingException e) {
	            throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
	        }
	    }
}